/******************************************************************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_plot.h"
#include "qwt_scale_map.h"
#include "qwt_plot_magnifier.h"

class QwtPlotMagnifier::PrivateData
{
public:
    PrivateData()
    {
        for (int axis = 0; axis < QwtAxis::AxisPositions; axis++)
            isAxisEnabled[ axis ] = true;
    }

    bool isAxisEnabled[ QwtAxis::AxisPositions ];
};

/*!
   Constructor
   \param canvas Plot canvas to be magnified
 */
QwtPlotMagnifier::QwtPlotMagnifier(QWidget* canvas) : QwtMagnifier(canvas)
{
    m_data = new PrivateData();
}

//! Destructor
QwtPlotMagnifier::~QwtPlotMagnifier()
{
    delete m_data;
}

/*!
   \brief En/Disable an axis

   Only Axes that are enabled will be zoomed.
   All other axes will remain unchanged.

   \param axisId Axis
   \param on On/Off

   \sa isAxisEnabled()
 */
void QwtPlotMagnifier::setAxisEnabled(QwtAxisId axisId, bool on)
{
    if (QwtAxis::isValid(axisId))
        m_data->isAxisEnabled[ axisId ] = on;
}

/*!
   Test if an axis is enabled

   \param axisId Axis
   \return True, if the axis is enabled

   \sa setAxisEnabled()
 */
bool QwtPlotMagnifier::isAxisEnabled(QwtAxisId axisId) const
{
    if (QwtAxis::isValid(axisId))
        return m_data->isAxisEnabled[ axisId ];

    return true;
}

//! Return observed plot canvas
QWidget* QwtPlotMagnifier::canvas()
{
    return parentWidget();
}

//! Return Observed plot canvas
const QWidget* QwtPlotMagnifier::canvas() const
{
    return parentWidget();
}

//! Return plot widget, containing the observed plot canvas
QwtPlot* QwtPlotMagnifier::plot()
{
    QWidget* w = canvas();
    if (w)
        w = w->parentWidget();

    return qobject_cast< QwtPlot* >(w);
}

//! Return plot widget, containing the observed plot canvas
const QwtPlot* QwtPlotMagnifier::plot() const
{
    const QWidget* w = canvas();
    if (w)
        w = w->parentWidget();

    return qobject_cast< const QwtPlot* >(w);
}

/*!
   Zoom in/out the axes scales
   \param factor A value < 1.0 zooms in, a value > 1.0 zooms out.
 */
void QwtPlotMagnifier::rescale(double factor)
{
    QwtPlot* plt = plot();
    if (plt == NULL)
        return;

    factor = qAbs(factor);
    if (factor == 1.0 || factor == 0.0)
        return;

    bool doReplot = false;

    const bool autoReplot = plt->autoReplot();
    plt->setAutoReplot(false);

    for (int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++) {
        {
            const QwtAxisId axisId(axisPos);

            if (isAxisEnabled(axisId)) {
                const QwtScaleMap scaleMap = plt->canvasMap(axisId);

                double v1 = scaleMap.s1();
                double v2 = scaleMap.s2();

                if (scaleMap.transformation()) {
                    // the coordinate system of the paint device is always linear

                    v1 = scaleMap.transform(v1);  // scaleMap.p1()
                    v2 = scaleMap.transform(v2);  // scaleMap.p2()
                }

                const double center  = 0.5 * (v1 + v2);
                const double width_2 = 0.5 * (v2 - v1) * factor;

                v1 = center - width_2;
                v2 = center + width_2;

                if (scaleMap.transformation()) {
                    v1 = scaleMap.invTransform(v1);
                    v2 = scaleMap.invTransform(v2);
                }

                plt->setAxisScale(axisId, v1, v2);
                doReplot = true;
            }
        }
    }

    plt->setAutoReplot(autoReplot);

    if (doReplot)
        plt->replot();
}
